#include "CPlayerOnlineData.h"
#include "../mainctrl.h"
#include "../energy/CEnergyMgr.h"

size_t CPlayerOnlineData::CountSize()
{
    return CUserStorage::CountSize()//身上背包
        + CUserEquip::CountSize()
        + CUserStorage::CountSize()//地表背包
        + CUserCard::CountSize()
        + CUserDailyTask::CountSize();
}

int CPlayerOnlineData::Init(const char* sBuff)
{
    int iRet;
    int iOffset = 0;

    //初始化装备
    iRet = _stUserEquip.Init(sBuff + iOffset);
    CHECK_RETURN(iRet);
    iOffset += CUserEquip::CountSize();

    //初始化背包+ 仓库
    iRet = _stUserStorage.Init(sBuff + iOffset);
    CHECK_RETURN(iRet);
    iOffset += CUserStorage::CountSize();

    iRet = _stUserGroudBag.Init(sBuff + iOffset);
    CHECK_RETURN(iRet);
    iOffset += CUserStorage::CountSize();

    iRet = _stUserCard.Init(sBuff + iOffset);
    CHECK_RETURN(iRet);
    iOffset += CUserCard::CountSize();

    iRet = _stUserDailyTask.Init(sBuff + iOffset);
    CHECK_RETURN(iRet);
    iOffset += CUserDailyTask::CountSize();

    //注意: 新增需要初始化HASH的结构时，需要在CPlayerOnlineData::Clear中调用结构的Clear函数, 否则会导致数据残留

    _bHashInited = true;

    return 0;
}

void CPlayerOnlineData::Clear ()
{
    _bIsInitFinish = false;
    _iRoleFighting = 0;
    _iTeamFighting = 0;

    _uiNowMapID = 0;
    _usMapPosX = 0;
    _usMapPosY = 0;

    _bCheckSysOpen = true;

    _stUserTask.Clean();
    _stUserRole.Clear();
    _stUserPartner.Clear();
    _stUserInstance.Clear();
    _stMealDrop.Clear();
    _stUserPet.Clean();
    _stUserAuction.Clear();
    _stUserShop.Clear ();

    if (_bHashInited)
    {
        _stUserStorage.Clear();
        _stUserEquip.Clear();
        _stUserGroudBag.Clear();
        _stUserCard.Clear();
        _stUserDailyTask.Clean();
    }

    _iLoginTime = 0;
    _iDefendValidInfo = 0;
    _iDefTotalOnlineTime = 0;

    _iLastSendWorldMsgTime = 0;

    _uiNowMount = 0;
    _usNowMountSkillLevel = 0;
}

int CPlayerOnlineData::InitData(unsigned int uiGID, CPlayerBaseInfo& stPlayerBaseInfo, CPlayerDetailInfo& stPlayerDetailInfo,
                                CPlayerDetailInfoEx1 & stPlayerDetailInfoEx1, CPlayerSnsDetailInfo& stPlayerSnsDetailInfo)
{
    int iRet = 0;
    CMainCtrl* pstMainCtrl = CMainCtrl::m_pstMain;

    if (uiGID != stPlayerBaseInfo._uiGID
        || uiGID != stPlayerDetailInfo._uiGID)
    {
        CT_ERROR(("init online data error, %u, %u, %u", uiGID, stPlayerBaseInfo._uiGID, stPlayerDetailInfo._uiGID));
        return RET_SYS_ERROR;
    }

    _uiGID = uiGID;
    _bIsInitFinish = false;

    _stUserTask.SetUserGid(uiGID);
    //初始化任务
    iRet = _stUserTask.Init(stPlayerBaseInfo._stUserTaskData);
    CHECK_RETURN(iRet);
    pstMainCtrl->m_stTaskMgr.UserDataTrigger(_stUserTask);

    _uiNowMapID = stPlayerBaseInfo._uiMapID;
    _usMapPosX = stPlayerBaseInfo._usXPos;
    _usMapPosY = stPlayerBaseInfo._usYPos;

    pstMainCtrl->m_stMountMgr.InitData(*this, stPlayerDetailInfoEx1._stMount);

    pstMainCtrl->m_stFashionMgr.InitData(stPlayerDetailInfoEx1._stUserFasion, *this);

    //初始化装备
    iRet = pstMainCtrl->m_stEquipMgr.InitData(_stUserEquip,
        stPlayerBaseInfo._uiGID, stPlayerDetailInfo._stUserEquip);
    if (iRet != 0)
    {
        CT_WARNING(("into equip error, ret %d", iRet));
        return iRet;
    }

    //初始化背包仓库
    iRet = pstMainCtrl->m_stStorageMgr.InitData(_stUserStorage, stPlayerDetailInfo._stUserStorage);
    if (iRet != 0)
    {
        CT_WARNING(("into storage error, ret %d", iRet));
        return iRet;
    }
    _stUserStorage._uiGID = _uiGID;

    /*初始化用户商店*/
    iRet = pstMainCtrl->m_stShopMgr.InitData(_stUserShop, stPlayerDetailInfo._stShopData);
    if (iRet != 0)
    {
        CT_WARNING(("into shop error, ret %d", iRet));
        return iRet;
    }
    _stUserShop._uiGid = _uiGID;

    //初始化家族
    iRet = pstMainCtrl->m_stClanMgr.InitUserData(stPlayerDetailInfo, stPlayerSnsDetailInfo);
    if (iRet != 0)
    {
        CT_WARNING(("into clan error, ret %d", iRet));
        return iRet;
    }

    //初始化副本
    iRet = _stUserInstance.SetData(stPlayerBaseInfo._stInstanceData);
    if (iRet != 0)
    {
        CT_WARNING(("into instance error, ret %d", iRet));
        return iRet;
    }

    //初始化日常任务
    _stUserDailyTask.SetUserGid(uiGID);
    iRet = _stUserDailyTask.InitData(stPlayerBaseInfo._stUserDailyTaskData);
    CHECK_RETURN(iRet);

    //初始化地表背包
    _stUserGroudBag.SetMaxBagGridCount(MAX_GROUD_GRID_COUNT);
    _stUserGroudBag.SetMaxWareHouseGridCount(0);
    _stUserGroudBag.SetEmpty();

    //初始化卡片
    iRet = pstMainCtrl->m_stCardMgr.InitData(_stUserCard, stPlayerBaseInfo._uiGID, stPlayerDetailInfo._stUserCardData);
    if (iRet != 0)
    {
        CT_WARNING(("into card error, ret %d", iRet));
        return iRet;
    }

    //初始化宠物 注意要放到初始化伙伴 角色之前
    _stUserPet.SetUserGid(uiGID);
    iRet = _stUserPet.InitData(stPlayerBaseInfo._stUserPetData);
    CHECK_RETURN(iRet);

    //初始化伙伴 注意要放到装备 背包初始化之后
    iRet = pstMainCtrl->m_stPartnerMgr.InitPartnerOnlineData(stPlayerBaseInfo, stPlayerDetailInfo, *this, stPlayerDetailInfoEx1);
    if (iRet != 0)
    {
        CT_WARNING(("init partner online data error, ret %d", iRet));
        return iRet;
    }

    //初始化角色技能
    iRet = _stUserRole.InitRoleSkill(stPlayerBaseInfo, stPlayerDetailInfo);
    if (iRet != 0)
    {
        CT_WARNING(("init role skill error, ret %d %u", iRet, uiGID));
        return iRet;
    }

    //初始化角色属性 这个要求放在装备 伙伴 技能等影响到二级属性的模块后面
    iRet = pstMainCtrl->m_stRoleMgr.ReCalcRoleExtAttr(stPlayerBaseInfo, stPlayerDetailInfo, *this, stPlayerDetailInfoEx1, false);
    if (iRet != 0)
    {
        CT_WARNING(("init role base and extension attr error, ret %d %u", iRet, uiGID));
        return iRet;
    }

    //初始化拍卖数据
    _stUserAuction = stPlayerBaseInfo._stUserAuctionData;

    //防沉迷信息
    _iLoginTime = stPlayerSnsDetailInfo._stCommInfo._iLastLogInTime;
    _iDefendValidInfo = stPlayerBaseInfo._iDefendValidInfo;
    _iDefTotalOnlineTime = stPlayerBaseInfo._iDefTotalOnlineTime;

    //初始化吃饭(精力系统)
    pstMainCtrl->m_stEnergyMgr.InitMealDrop(stPlayerBaseInfo._stUserEnergy, _stMealDrop);

    _bIsInitFinish = true;
    pstMainCtrl->m_stMatrixMgr.ReCalcMainFighting(stPlayerBaseInfo, stPlayerDetailInfo, *this);

    return 0;
}
